package slinks.extensions.amf.orm
{
	
	import flash.utils.IDataInput;
	import flash.utils.IDataOutput;
	import flash.utils.IExternalizable;
	
	import mx.collections.ArrayCollection;
	import mx.collections.errors.ItemPendingError;
	import mx.controls.Alert;
	import mx.events.CollectionEvent;
	import mx.events.CollectionEventKind;
	import mx.rpc.IResponder;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	
	
	[Bindable]
    [RemoteClass(alias="slinks.extensions.amf.orm.PersistentCollectionProxy")]
	public class PersistentCollectionProxy extends ArrayCollection
	{
		
		public var owner:Object;
		
		public var association:Object;
		
		public var typeClass:Object;
		
		public var dirty:Boolean;
		
		public var isInitialized:Boolean;
				
		private var pendingErrors:Array = new Array();
		
		
		//public var collectionChanges:Array;
		
		
		public function PersistentCollectionProxy()
		{
			super();

		}
		
		
		override public function get source():Array
	    {
	        return super.source;
	    }
	
	    /**
	     *  @private
	     */
	    override public function set source(s:Array):void
	    {
	        super.source = s;
	    }
		
		//FIXME: Security!! make sure service is secure and we do not rely on serviceLocator. 
		// It looks like Flex expects the lenght to be know even before the collection is intilaized. 
		override public function get length():int{
			if(isInitialized){
				return super.length;
			}else{
				//first make sure we are not just still waiting on results 
	/* 			if(pendingErrors.length == 0){
					// not intialized fetch data 
					DelegateHelper
						.executeRemoteFunction("lazyService"
											   ,"initCollection"
											   ,lazyIntializationResultHandler
											   ,faultHandler
											   ,null
											   ,key,role,type);
	
				}
				var error:ItemPendingError = new ItemPendingError("Lazy Intialization Pending"); */
			/* 	pendingErrors.push(error);
				
				throw error; */
				return -1;
			}
		}
		
		
		override public function getItemAt( index : int, prefetch : int = 0 ) : Object {
			if(isInitialized){
				return super.getItemAt(index,prefetch);
			}else{
				//first make sure we are not just still waiting on results 
				if(pendingErrors.length == 0){
					// not intialized fetch data 
/*					DelegateHelper
						.executeRemoteFunction("lazyService"
											   ,"initCollection"
											   ,lazyIntializationResultHandler
											   ,faultHandler
											   ,null
											   ,key,role,type);*/
	
				}
				var error:ItemPendingError = new ItemPendingError("Lazy Intialization Pending");
				pendingErrors.push(error);
				
				throw error;
			}
		}
		

		
		private function lazyIntializationResultHandler(event:ResultEvent,token:Object=null) : void{		
			if(event.result){
				isInitialized = true;
				source = event.result as Array;
				
				updateResponders(event);			
			}else{
				 // TODO: add error processing, logging etc.
				Alert.show("Failed retrieving data"); 
			}
			
			//FIXME: For Some reason Tree doesn't see change event. 
			dispatchEvent(new CollectionEvent(CollectionEvent.COLLECTION_CHANGE,true,false,CollectionEventKind.RESET));
	
		}
		
		private function updateResponders( event : ResultEvent ) : void {

                /*
                 * We throw ItemPendingErrors per RPC request,
                 * so as we make RPC requests per page,
                 * get the ItemPendingError for this page
                 */
			for each(var itemPendingError:ItemPendingError in pendingErrors){
                var responders : Array = itemPendingError.responders;
                
				if(responders != null){
	                for( var j : int = 0; j!=responders.length; j++){
	                      var responder : IResponder = responders[ j ] as IResponder;
	                      responder.result( event );
	                }
                }
			}
			pendingErrors = new Array();
         }
		
		private  function faultHandler(event:FaultEvent,token:Object=null ) : void{	
	        for each(var itemPendingError:ItemPendingError in pendingErrors){
                var responders : Array = itemPendingError.responders;
                
				if(responders != null){
	                for( var j : int = 0; j!=responders.length; j++){
	                      var responder : IResponder = responders[ j ] as IResponder;
	                      responder.fault( event );
	                }
                }
			}
			pendingErrors = new Array();      		
	        // TODO: add error processing, logging etc.
 
		}
		
		private function collectionChangeHandler(event:CollectionEvent):void{
			
			//FIXME: Track cahnges to collection. 
			// Currently everything is just being rewritten on the server. 
			dirty = true;
			
	/* 		var changeOperation:CollectionChangeOperation = new CollectionChangeOperation();
			
			if(event.kind == CollectionEventKind.ADD){
				
			}else if(event.kind == CollectionEventKind.REMOVE){
				
			}else if(event.kind == CollectionEventKind.RESET){
				
			} */
			
			// FIXME: Track changes so updates that do not require intilization can still hapen without fetching object graph.  
			if(!isInitialized){
				//TODO: Prevent access to remote services. Since this could cause a data cooruption problem. 
				throw new Error("Unitialized Collection Access");
				
			}
			
		}
		
		
		

	}
}